home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 February / EnigmA AMIGA RUN 04 (1996)(G.R. Edizioni)(IT)[!][issue 1996-02][Skylink CD III].iso / earcd / comm2 / xbtx.lha / Source / ModemService.cpp < prev    next >
C/C++ Source or Header  |  1995-12-03  |  9KB  |  474 lines

  1. /*
  2. **    $Id: ModemService.cpp 1.6 1995/12/03 12:16:23 olsen Exp olsen $
  3. **
  4. **    :ts=4
  5. */
  6.  
  7. /*
  8.  * Copyright © 1995 by Olaf Barthel, All Rights Reserved
  9.  *
  10.  * Redistribution and use in source and binary forms, with or without
  11.  * modification, are permitted provided that the following conditions
  12.  * are met:
  13.  * 1. Redistributions of source code must retain the above copyright
  14.  *    notice, this list of conditions and the following disclaimer.
  15.  * 2. Redistributions in binary form must reproduce the above copyright
  16.  *    notice, this list of conditions and the following disclaimer in the
  17.  *    documentation and/or other materials provided with the distribution.
  18.  *
  19.  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
  20.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  21.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO
  22.  * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  23.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  24.  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
  25.  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  26.  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  27.  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  28.  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29.  *
  30.  * This software has not been validated by the ``Bundesamt fuer Zulassungen in
  31.  * der Telekommunikation'' of the ``Deutsche Bundepost Telekom'' and thus
  32.  * must not be used for accessing the BTX-Network of the Telekom in Germany.
  33.  *
  34.  * Diese Software hat keine Zulassung durch das Bundesamt fuer Zulassungen in
  35.  * der Telekommunikation der Deutschen Bundespost Telekom und darf daher nicht
  36.  * am Netz der Deutschen Bundespost Telekom in Deutschland betrieben werden.
  37.  */
  38.  
  39. /****************************************************************************/
  40.  
  41. #include <dos/dos.h>
  42.  
  43. #include <devices/timer.h>
  44.  
  45. #include <clib/exec_protos.h>
  46. #include <clib/dos_protos.h>
  47.  
  48. #ifdef __SASC
  49. #include <pragmas/exec_pragmas.h>
  50. #include <pragmas/dos_pragmas.h>
  51.  
  52. extern struct ExecBase        *SysBase;
  53. extern struct DosLibrary    *DOSBase;
  54. #endif    // _SASC
  55.  
  56. #include <string.h>
  57. #include <stdio.h>
  58.  
  59. /****************************************************************************/
  60.  
  61. #define D(x)
  62.  
  63. /****************************************************************************/
  64.  
  65. #ifndef _MODEMSERVICE_HPP
  66. #include "ModemService.hpp"
  67. #endif
  68.  
  69. /****************************************************************************/
  70.  
  71. ModemService::ModemService()
  72. {
  73.     AppChannel        = NULL;
  74.     Connected        = FALSE;
  75.  
  76.     HangupCommand    = NULL;
  77.  
  78.     TimePort        = NULL;
  79.     TimeRequest        = NULL;
  80. }
  81.  
  82. ModemService::~ModemService()
  83. {
  84.     Close();
  85. }
  86.  
  87. LONG ModemService::Open(IOChannel *Channel,BTXDisplay *Display)
  88. {
  89.     if(TimePort = CreateMsgPort())
  90.     {
  91.         TimeMask = 1UL << TimePort->mp_SigBit;
  92.  
  93.         if(TimeRequest = (struct timerequest *)CreateIORequest(TimePort,sizeof(timerequest)))
  94.         {
  95.             if(OpenDevice((UBYTE *)TIMERNAME,UNIT_VBLANK,(struct IORequest *)TimeRequest,NULL))
  96.             {
  97.                 DeleteIORequest((struct IORequest *)TimeRequest);
  98.                 TimeRequest = NULL;
  99.             }
  100.         }
  101.     }
  102.  
  103.     if(TimeRequest)
  104.     {
  105.         AppChannel = Channel;
  106.         AppDisplay = Display;
  107.  
  108.         return(0);
  109.     }
  110.  
  111.     Close();
  112.  
  113.     return(-1);
  114. }
  115.  
  116. VOID ModemService::Close(VOID)
  117. {
  118.     if(Connected)
  119.         Disconnect();
  120.  
  121.     if(TimeRequest)
  122.     {
  123.         CloseDevice((struct IORequest *)TimeRequest);
  124.  
  125.         DeleteIORequest((struct IORequest *)TimeRequest);
  126.         TimeRequest = NULL;
  127.     }
  128.  
  129.     if(TimePort)
  130.     {
  131.         DeleteMsgPort(TimePort);
  132.         TimePort = NULL;
  133.     }
  134.  
  135.     if(HangupCommand)
  136.     {
  137.         delete HangupCommand;
  138.         HangupCommand = NULL;
  139.     }
  140.  
  141.     AppChannel = NULL;
  142. }
  143.  
  144. LONG ModemService::Connect(CONST STRPTR Init,CONST STRPTR Dial,CONST STRPTR Number,CONST STRPTR Hangup,LONG Timeout)
  145. {
  146.     STATIC STRPTR ResponseTable[] =
  147.     {
  148.         "OK",
  149.         "NO CARRIER",
  150.         "ERROR",
  151.         "BUSY",
  152.         "NO DIALTONE",
  153.         "CONNECT",
  154.         "NO ANSWER",
  155.         "RINGING",
  156.         "RING",
  157.  
  158.         NULL
  159.     };
  160.  
  161.     char    Buffer[40];
  162.     LONG    Result,i;
  163.     ULONG    Signals;
  164.  
  165.     AppDisplay->PutLine(NULL);
  166.  
  167.     if(!HangupCommand)
  168.     {
  169.         if(HangupCommand = new char[strlen(Hangup) + 1])
  170.             strcpy(HangupCommand,Hangup);
  171.     }
  172.  
  173.     SetSignal(0,TimeMask);
  174.  
  175.     TimeRequest->tr_node.io_Command    = TR_ADDREQUEST;
  176.     TimeRequest->tr_time.tv_secs    = Timeout;
  177.     TimeRequest->tr_time.tv_micro    = 0;
  178.  
  179.     SendIO((struct IORequest *)TimeRequest);
  180.  
  181.     D(printf("timeout = %ld\n",Timeout));
  182.  
  183.     if(Init[0])
  184.     {
  185.         BOOL Done = FALSE;
  186.  
  187.         SendCommand(Init);
  188.  
  189.         do
  190.         {
  191.             Signals = Wait(AppChannel->WaitMask() | AppDisplay->WaitMask() | SIGBREAKF_CTRL_C | TimeMask);
  192.  
  193.             if(Signals & SIGBREAKF_CTRL_C)
  194.             {
  195.                 AppDisplay->PutLine("Aborted");
  196.  
  197.                 if(!CheckIO((struct IORequest *)TimeRequest))
  198.                     AbortIO((struct IORequest *)TimeRequest);
  199.  
  200.                 WaitIO((struct IORequest *)TimeRequest);
  201.  
  202.                 return(MODEM_NoCarrier);
  203.             }
  204.  
  205.             if(Signals & AppDisplay->WaitMask())
  206.             {
  207.                 Result = AppDisplay->GetChar();
  208.  
  209.                 if(Result == '\033' || Result == ('C' & 0x1F))
  210.                 {
  211.                     AppDisplay->PutLine("Aborted");
  212.  
  213.                     if(!CheckIO((struct IORequest *)TimeRequest))
  214.                         AbortIO((struct IORequest *)TimeRequest);
  215.  
  216.                     WaitIO((struct IORequest *)TimeRequest);
  217.  
  218.                     return(MODEM_NoCarrier);
  219.                 }
  220.             }
  221.  
  222.             if(Signals & AppChannel->WaitMask())
  223.             {
  224.                 Result = GetLine(Buffer,40);
  225.  
  226.                 D(printf("result %ld buffer |%s|\n",Result,Buffer));
  227.  
  228.                 if(Result > 0)
  229.                 {
  230.                     AppDisplay->PutLine(Buffer);
  231.  
  232.                     for(i = 0 ; ResponseTable[i] ; i++)
  233.                     {
  234.                         if(strstr(Buffer,ResponseTable[i]))
  235.                         {
  236.                             if(i == MODEM_Ok)
  237.                                 Done = TRUE;
  238.                             else
  239.                             {
  240.                                 AppDisplay->PutLine("Error while initializing modem");
  241.  
  242.                                 if(!CheckIO((struct IORequest *)TimeRequest))
  243.                                     AbortIO((struct IORequest *)TimeRequest);
  244.  
  245.                                 WaitIO((struct IORequest *)TimeRequest);
  246.  
  247.                                 return(i);
  248.                             }
  249.                         }
  250.                     }
  251.                 }
  252.             }
  253.  
  254.             if(Signals & TimeMask)
  255.             {
  256.                 WaitIO((struct IORequest *)TimeRequest);
  257.  
  258.                 if(Done)
  259.                 {
  260.                     TimeRequest->tr_node.io_Command    = TR_ADDREQUEST;
  261.                     TimeRequest->tr_time.tv_secs    = Timeout;
  262.                     TimeRequest->tr_time.tv_micro    = 0;
  263.  
  264.                     SendIO((struct IORequest *)TimeRequest);
  265.                 }
  266.                 else
  267.                 {
  268.                     AppDisplay->PutLine("Timeout while initializing modem");
  269.  
  270.                     return(MODEM_Timeout);
  271.                 }
  272.             }
  273.         }
  274.         while(!Done);
  275.     }
  276.  
  277.     SendCommand(Dial);
  278.     SendCommand(Number);
  279.     SendCommand("^M");
  280.  
  281.     for(;;)
  282.     {
  283.         Signals = Wait(AppChannel->WaitMask() | AppDisplay->WaitMask() | TimeMask | SIGBREAKF_CTRL_C);
  284.  
  285.         if(Signals & SIGBREAKF_CTRL_C)
  286.         {
  287.             AppDisplay->PutLine("Aborted");
  288.  
  289.             if(!CheckIO((struct IORequest *)TimeRequest))
  290.                 AbortIO((struct IORequest *)TimeRequest);
  291.  
  292.             WaitIO((struct IORequest *)TimeRequest);
  293.  
  294.             SendCommand("^M");
  295.  
  296.             return(MODEM_NoCarrier);
  297.         }
  298.  
  299.         if(Signals & AppDisplay->WaitMask())
  300.         {
  301.             LONG Result = AppDisplay->GetChar();
  302.  
  303.             if(Result == '\033' || Result == ('C' & 0x1F))
  304.             {
  305.                 AppDisplay->PutLine("Aborted");
  306.  
  307.                 if(!CheckIO((struct IORequest *)TimeRequest))
  308.                     AbortIO((struct IORequest *)TimeRequest);
  309.  
  310.                 WaitIO((struct IORequest *)TimeRequest);
  311.  
  312.                 SendCommand("^M");
  313.  
  314.                 return(MODEM_NoCarrier);
  315.             }
  316.         }
  317.  
  318.         if(Signals & AppChannel->WaitMask())
  319.         {
  320.             Result = GetLine(Buffer,40);
  321.  
  322.             if(Result > 0)
  323.             {
  324.                 AppDisplay->PutLine(Buffer);
  325.  
  326.                 for(i = 0 ; ResponseTable[i] ; i++)
  327.                 {
  328.                     if(strstr(Buffer,ResponseTable[i]))
  329.                     {
  330.                         AppChannel->Flush();
  331.  
  332.                         if(!CheckIO((struct IORequest *)TimeRequest))
  333.                             AbortIO((struct IORequest *)TimeRequest);
  334.  
  335.                         WaitIO((struct IORequest *)TimeRequest);
  336.  
  337.                         if(i == MODEM_Connect)
  338.                         {
  339.                             Connected = TRUE;
  340.  
  341.                             return(i);
  342.                         }
  343.  
  344.                         if(i != MODEM_Ringing && i != MODEM_Ring)
  345.                         {
  346.                             D(printf("i %ld MODEM_Ringing %ld MODEM_Ring %ld\n",i,MODEM_Ringing,MODEM_Ring));
  347.  
  348.                             AppDisplay->PutLine("Error while dialing");
  349.                             return(i);
  350.                         }
  351.                     }
  352.                 }
  353.             }
  354.         }
  355.  
  356.         if(Signals & TimeMask)
  357.         {
  358.             WaitIO((struct IORequest *)TimeRequest);
  359.  
  360.             AppDisplay->PutLine("Timeout while dialing");
  361.  
  362.             SendCommand("^M");
  363.  
  364.             return(MODEM_Timeout);
  365.         }
  366.     }
  367. }
  368.  
  369. VOID ModemService::Disconnect(VOID)
  370. {
  371.     if(Connected)
  372.     {
  373.         if(HangupCommand)
  374.             SendCommand(HangupCommand);
  375.  
  376.         Connected = FALSE;
  377.     }
  378.  
  379.     if(HangupCommand)
  380.     {
  381.         delete HangupCommand;
  382.         HangupCommand = NULL;
  383.     }
  384. }
  385.  
  386. LONG ModemService::GetLine(STRPTR Buffer,LONG Size)
  387. {
  388.     LONG Len = 0,Result;
  389.  
  390.     for(;;)
  391.     {
  392.         Result = AppChannel->GetCharDirect(4);
  393.  
  394.         if(Result < 0 || Result == '\r')
  395.         {
  396.             Buffer[Len] = 0;
  397.  
  398.             return(Len);
  399.         }
  400.         else
  401.         {
  402.             if(Result == '\n' || (!Len && Result == ' '))
  403.                 continue;
  404.  
  405.             if(Result < ' ')
  406.             {
  407.                 Result += ' ';
  408.  
  409.                 Buffer[Len++] = '^';
  410.  
  411.                 if(Len == Size - 1)
  412.                 {
  413.                     Buffer[Len] = 0;
  414.  
  415.                     return(Len);
  416.                 }
  417.             }
  418.  
  419.             Buffer[Len++] = (char)Result;
  420.  
  421.             if(Len == Size - 1)
  422.             {
  423.                 Buffer[Len] = 0;
  424.  
  425.                 return(Len);
  426.             }
  427.         }
  428.     }
  429. }
  430.  
  431. VOID ModemService::SendCommand(CONST STRPTR Command)
  432. {
  433.     BOOL Escape;
  434.     LONG i;
  435.     char c;
  436.  
  437.     for(i = 0, Escape = FALSE ; i < strlen(Command) ; i++)
  438.     {
  439.         switch(Command[i])
  440.         {
  441.             case '^':
  442.  
  443.                 if(Escape)
  444.                     AppChannel->PutCharDirect('^');
  445.  
  446.                 Escape ^= TRUE;
  447.                 break;
  448.  
  449.             case '~':
  450.  
  451.                 if(Escape)
  452.                     AppChannel->PutCharDirect('~');
  453.                 else
  454.                     Delay(TICKS_PER_SECOND);
  455.  
  456.                 break;
  457.  
  458.             default:
  459.  
  460.                 if(Escape)
  461.                 {
  462.                     c = (char)(Command[i] & 0x1F);
  463.  
  464.                     Escape = FALSE;
  465.                 }
  466.                 else
  467.                     c = Command[i];
  468.  
  469.                 AppChannel->PutCharDirect(c);
  470.                 break;
  471.         }
  472.     }
  473. }
  474.